package com.example.myapplication.geolocation

import android.Manifest
import android.annotation.SuppressLint
import android.content.Context
import android.content.pm.PackageManager
import android.location.Location
import android.os.Looper
import androidx.core.app.ActivityCompat
import androidx.lifecycle.MutableLiveData
import com.example.myapplication.geofence.GeofenceManager
import com.google.android.gms.location.*
import java.lang.ref.WeakReference

/**
 * Author: Jaydenyan
 * Date: 2022/5/9 18:09
 * Description:
 * History:
 * <author> <time> <version> <desc>
 * Jaydenyan 2022/5/9 1.0 首次创建
</desc></version></time></author> */
class GoogleGeolocation : IBaseGeoLocation {
    private val listenerList: ArrayList<WeakReference<GeoLocationCallback>> = ArrayList<WeakReference<GeoLocationCallback>>()
    private fun checkContainsListener(listener: GeoLocationCallback): Boolean {
        for (weakReference in listenerList) {
            if (weakReference.get() != null) {
                return weakReference.get() === listener
            }
        }
        return false
    }

    public fun addLocationChangedListener(mGeoLocationCallback: GeoLocationCallback) {
        if (!checkContainsListener(mGeoLocationCallback)) {
            val scanListenerWeakReference: WeakReference<GeoLocationCallback> =
                WeakReference<GeoLocationCallback>(mGeoLocationCallback)
            listenerList.add(scanListenerWeakReference)
        }
    }

    public fun callLocationChangedListener(result: Location) {
        for (weakReference in listenerList) {
            if (weakReference.get() != null) {
                weakReference.get()?.onLocationChanged(result)
            }
        }
    }

    public fun removeLocationChangedListener(listener: GeoLocationCallback) {
        val iterator: MutableIterator<WeakReference<GeoLocationCallback>> =
            listenerList.iterator()
        while (iterator.hasNext()) {
            val weakReference: WeakReference<GeoLocationCallback> = iterator.next()
            if (weakReference.get() == null) {
                iterator.remove()
            } else if (weakReference.get() === listener) iterator.remove()
        }
    }

    companion object {
        val instance by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
            GoogleGeolocation()
        }
    }

    private var mListener: GeoLocationCallback? = null
    private var mFusedLocationProviderClient: FusedLocationProviderClient? = null
    private lateinit var mLocationCallback: LocationCallback
    private lateinit var locationRequest: LocationRequest
    override fun initLocationClient(mContext: Context, interval: Long?, fastestInterval: Long?): GoogleGeolocation {
        locationRequest = LocationRequest()
            .setInterval(interval ?: 5000)
            .setFastestInterval(fastestInterval ?: 1000)
            .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
        mLocationCallback = object : LocationCallback() {
            override fun onLocationResult(result: LocationResult) {
                super.onLocationResult(result)
                val locationList: List<Location> = result.locations
                if (locationList.isNotEmpty()) {
                    val location: Location = locationList.last()
                    callLocationChangedListener(location)
                }

            }
        }
        mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(mContext.applicationContext)
        return this
    }


    @SuppressLint("MissingPermission")
    override fun onStartLocation(mContext: Context, listener: GeoLocationCallback) {
        addLocationChangedListener(listener)
        if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED ||
            ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED
        ) {
            mFusedLocationProviderClient?.requestLocationUpdates(locationRequest, mLocationCallback, Looper.myLooper())
        }
    }

    override fun onStopLocation(listener: GeoLocationCallback) {
        removeLocationChangedListener(listener)
        if (listenerList.isEmpty())
            mFusedLocationProviderClient?.removeLocationUpdates(mLocationCallback)
    }
}